package com.sym.demo.tree.tree2;

import cn.hutool.core.util.ObjectUtil;
import com.sym.demo.entity.BaseTreeEntity;
import lombok.Data;

/**
 * @author suyongming
 * @date ：2021/4/10 10:29
 */
@Data
public class Tree2Node<T extends BaseTreeEntity> {
    private Tree2Node<T> pNode;
    private Tree2Node<T> lNode;
    private Tree2Node<T> rNode;

    /**
     * treeId || key
     */
    private Integer treeId;
    /**
     * value
     */
    private T obj;

    /**
     * 新增
     */
    public void put(T saveObj) {
        if (ObjectUtil.isNull(this.treeId)) {
            // 第一次进来
            this.treeId = saveObj.getTreeId();
            this.obj = saveObj;
            return;
        } else {
            put(this, saveObj);
        }
    }

    private void put(Tree2Node<T> tree2Node, T saveObj) {
        if (saveObj.getTreeId() < tree2Node.getTreeId()) {
            if (ObjectUtil.isNull(tree2Node.lNode)) {
                tree2Node.lNode = new Tree2Node<>();
                tree2Node.lNode.pNode = tree2Node;
                tree2Node.lNode.treeId = saveObj.getTreeId();
                tree2Node.lNode.obj = saveObj;
                return;

            } else {
                // 下左楼
                tree2Node.put(tree2Node.lNode, saveObj);
            }
        }

        if (saveObj.getTreeId() > tree2Node.getTreeId()) {
            if (ObjectUtil.isNull(tree2Node.rNode)) {
                tree2Node.rNode = new Tree2Node<>();
                tree2Node.rNode.pNode = tree2Node;
                tree2Node.rNode.treeId = saveObj.getTreeId();
                tree2Node.rNode.obj = saveObj;
                return;

            } else {
                // 下右楼
                tree2Node.put(tree2Node.rNode, saveObj);
            }
        }

    }

    /**
     * 根据对象的索引删除
     */
    public boolean delete(Integer treeId) {
        if (ObjectUtil.isNull(treeId) || ObjectUtil.isNull(this)) {
            return false;
        }

        delete(this, treeId);
        return false;
    }

    private boolean delete(Tree2Node tree2Node, Integer treeId) {
        // TODO 找到了需要被删除的节点
        if (tree2Node.getTreeId().equals(treeId)) {
            // 被删除结点 已经是叶子节点了
            if(ObjectUtil.isNull(tree2Node.lNode) && ObjectUtil.isNull(tree2Node.rNode)) {
                tree2Node = null;
            }

            // 如果左右两个节点都在
            if(ObjectUtil.isNotNull(tree2Node.lNode) && ObjectUtil.isNotNull(tree2Node.rNode)) {
                tree2Node.lNode.pNode = tree2Node.pNode;
                tree2Node.lNode.rNode = tree2Node.rNode;

                tree2Node.pNode.lNode = tree2Node.lNode;

                tree2Node.rNode.pNode = tree2Node.lNode;
            }

            // 只有左节点
            if(ObjectUtil.isNotNull(tree2Node.lNode) && ObjectUtil.isNull(tree2Node.rNode)) {
                tree2Node.lNode.pNode = tree2Node.pNode;
                tree2Node.pNode.lNode = tree2Node.lNode;
            }

            // 只有右节点
            if(ObjectUtil.isNull(tree2Node.lNode) && ObjectUtil.isNotNull(tree2Node.rNode)) {
                tree2Node.rNode.pNode = tree2Node.pNode;
                tree2Node.pNode.rNode = tree2Node.rNode;
            }


            return true;
        }

        if (treeId > tree2Node.getTreeId()) {
            return delete(tree2Node.rNode, treeId);
        }

        if (treeId < tree2Node.getTreeId()) {
            return delete(tree2Node.lNode, treeId);
        }

        return false;
    }

    /**
     * Query
     *
     * @Param treeId
     */
    public T get(Integer treeId) {
        if (ObjectUtil.isNull(treeId) || ObjectUtil.isNull(this)) {
            return null;
        }

        return get(this, treeId);
    }

    private T get(Tree2Node tree2Node, Integer treeId) {
        if (tree2Node.getTreeId().equals(treeId)) {
            return (T) tree2Node.getObj();
        }

        if (treeId > tree2Node.getTreeId()) {
            return get(tree2Node.rNode, treeId);
        }

        if (treeId < tree2Node.getTreeId()) {
            return get(tree2Node.lNode, treeId);
        }
        return null;
    }
}
